﻿using Ndns.Packet.Text;
using System;
using System.IO;
using System.Text;

namespace Ndns.Packet.Helpers
{
    internal static class PunycodeEncodingExtensionsForDns
    {

        public static string DecodeDomainPart(this PunycodeEncoding encoding, string s)
        {
            if (s.Length > 4 && s.Substring(0, 4).ToLowerInvariant() == "xn--")
                return encoding.GetString(Encoding.ASCII.GetBytes(s.Substring(4)));
            else
                return s;
        }

        public static string DecodeDomainPart(this PunycodeEncoding encoding, byte[] bytes)
        {
            if (bytes.Length > 4)
            {
                if (bytes[0] == s_punycodePreamble[0] &&
                    bytes[1] == s_punycodePreamble[1] &&
                    bytes[2] == s_punycodePreamble[2] &&
                    bytes[3] == s_punycodePreamble[3])
                {
                    return encoding.GetString(bytes, 4, bytes.Length - 4);
                }
            }
            return Encoding.ASCII.GetString(bytes);
        }

        public static string EncodeDomainPart(this PunycodeEncoding encoding, string s)
        {
            if (encoding.IsEncodingRequired(s))
                return "xn--" + Encoding.ASCII.GetString(encoding.GetBytes(s));
            else
                return s;
        }

        private static byte[] s_punycodePreamble = Encoding.ASCII.GetBytes("xn--");

        public static int EncodeDomainPartToStream(this PunycodeEncoding encoding, string part, Stream stream)
        {
            byte[] bytes;
            int count = 0;
            if (encoding.IsEncodingRequired(part))
            {
                count += 4;
                bytes = encoding.GetBytes(part);
                stream.Write(s_punycodePreamble);
                stream.Write(bytes);
            }
            else
            {
                bytes = Encoding.ASCII.GetBytes(part);
                stream.Write(bytes);
            }
            return count + bytes.Length;
        }
        public static byte[] EncodeDomainPartToArray(this PunycodeEncoding encoding, string part)
        {
            if (encoding.IsEncodingRequired(part))
            {
                var bytes = encoding.GetBytes(part);
                var r = new byte[4 + bytes.Length];
                r[0] = s_punycodePreamble[0];
                r[1] = s_punycodePreamble[1];
                r[2] = s_punycodePreamble[2];
                r[3] = s_punycodePreamble[3];
                Array.Copy(bytes, 0, r, 4, bytes.Length);
                return r;
            }
            else
            {
                return Encoding.ASCII.GetBytes(part);
            }
        }
    }
}
